using System;
using System.Collections;
using System.ComponentModel;
using System.DirectoryServices.Protocols;
using InfiniTec.Data;

namespace InfiniTec.DirectoryServices
{
	internal static class PropertyEncoder
	{
		/// <summary>
		/// Returns the modifications made to the property as a <see cref="DirectoryAttributeModification"/>
		/// </summary>
		/// <returns>The modifications made to the property as a <see cref="DirectoryAttributeModification"/></returns>
		public static DirectoryAttributeModification GetPropertyModification(Property property)
		{
			IPropertyInfo propertyInfo = property;

			var modification = new DirectoryAttributeModification {Name = propertyInfo.PropertyDefinition.Name};
			//modification.Operation = (_IsNew) ? DirectoryAttributeOperation.Add : DirectoryAttributeOperation.Replace;

			if (propertyInfo.PropertyDefinition.Type == typeof (byte[]))
			{
				modification.Add((byte[]) (propertyInfo.Value));
			}
			else if (propertyInfo.PropertyDefinition.Type == typeof (Uri))
			{
				modification.Add((Uri) propertyInfo.Value);
			}
			else if (propertyInfo.PropertyDefinition.Type.IsClass)
			{
				if (propertyInfo.PropertyValueIsNull) modification.Clear();
				else
					modification.Add(
						TypeDescriptor.GetConverter(propertyInfo.PropertyDefinition.Type).ConvertToString(propertyInfo.Value));
			}
			else
			{
				modification.Add(
					TypeDescriptor.GetConverter(propertyInfo.PropertyDefinition.Type).ConvertToString(propertyInfo.Value));
			}

			return modification;
		}

		/// <summary>
		/// Returns the modifications made to the property as a <see cref="DirectoryAttributeModification"/>
		/// </summary>
		/// <returns>The modifications made to the property as a <see cref="DirectoryAttributeModification"/></returns>
		public static DirectoryAttributeModification GetMultivaluedPropertyModification(Property property)
		{
			IPropertyInfo propertyInfo = property;
			TypeConverter converter = TypeDescriptor.GetConverter(propertyInfo.PropertyDefinition.Type);

			var modification = new DirectoryAttributeModification
			                   	{
			                   		Name = propertyInfo.PropertyDefinition.Name,
			                   		Operation = propertyInfo.PropertyValueIsNull ? DirectoryAttributeOperation.Replace : DirectoryAttributeOperation.Delete
			                   	};
			//modification.Operation = (_IsNew) ? DirectoryAttributeOperation.Add : DirectoryAttributeOperation.Replace;

			if (propertyInfo.PropertyDefinition.Type == typeof (byte[]))
			{
				foreach (object value in (IEnumerable) propertyInfo.Value)
				{
					modification.Add((byte[]) value);
				}
			}
			else if (propertyInfo.PropertyDefinition.Type == typeof (Uri))
			{
				foreach (Uri value in (IEnumerable) propertyInfo.Value)
				{
					modification.Add(value);
				}
			}
			else
			{
				foreach (object value in (IEnumerable) propertyInfo.Value)
				{
					modification.Add(converter.ConvertToString(value));
				}
			}

			return modification;
		}
	}
}